//-----------------------------------------------------
// application.h
//-----------------------------------------------------

/**
 * comment here
 */

#pragma once

#include <string>
#include <map>

namespace application {

	class CApplicationState;

	class CApplication {

	protected:

		bool _termination;	// Tells if the application will end with the current step of the main loop.
		bool _initialized;					// Tells if the application has been initialized
		static CApplication* _instance;		// Single instance of the application.

		typedef std::map<std::string, CApplicationState*> TStateTable;

		TStateTable _states;				// Hash table with the application states
		CApplicationState *_currentState;	// Current application state
		CApplicationState *_nextState;		// Next application state

	public:

		// Class constructor
		CApplication();

		// Class destructor
		virtual ~CApplication() {}

		// Returns the application instance. Implements a singleton through the constructor
		static CApplication* getApp();

		// Initialize the application. @return false if the initialization failed
		virtual bool init();

		// Ends the application freeing resources
		void end();

		// Function to execute the application
		virtual void run();

		// Called from outside the application (usually by an state)
		// This function is meant to be called while the method run is running.
		void requestTermination() {
			_termination = true;
		}

		// Function to ask if someone has requested the application to end.
		// @return Returns whether the application will end within the current loop execution.
		bool terminationRequested() {
			return _termination;
		}

		/************************************************************************/
		/*                        STATE FUNCTIONS                               */
		/************************************************************************/

		// Add a state to the application. The application has to delete the state on exit
		void addState(const std::string &name, CApplicationState *newState);

		// Sets the application state from his name. the state will be set on the next step
		// of the main loop. @param state name. @return true if the state exists
		bool setState(const std::string &name);

		// Returns the current state of the application
		CApplicationState *getState() { return _currentState; }

	protected:

		// Function to step the main loop of the application.
		virtual void step();

		// Function to change the state notifying the out state and the in state
		void changeState();

	}; // class CApplication

	inline CApplication* CApplication::getApp() {
		return _instance;
	}

} // namespace application
